﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace ComicsEditor
{
    public partial class TextControl : UserControl
    {
        private PageEditor pageEditor;
        private PageInfo pageInfo;
        private Text text;

        public TextControl()
        {
            InitializeComponent();

            comboFontName.Items.Add("comic");
            comboFontName.Items.Add("serif");
            comboFontName.Items.Add("sans-serif");
            comboFontName.Items.Add("monospace");
            foreach (FontFamily family in FontFamily.Families)
                comboFontName.Items.Add(family.GetName(0));
            comboFontName.SelectedItem = "comic";
            comboMode.SelectedIndex = 0;
            comboAlignment.SelectedIndex = 0;
            comboBaseline.SelectedIndex = 0;
        }

        public void Activate(PageEditor pageEditor)
        {
            this.pageEditor = pageEditor;
            Visible = true;
            toolStripButtonTextSelect.Checked = true;
            updateCurrentText();
        }

        public void Disactivate()
        {
            resetToolStripText(null);
            Visible = false;
            if (text != null)
            {
                text.EndEdit();
                pageEditor.UpdatePage();
            }
        }

        public void Bind(PageInfo pageInfo)
        {
            if (text != null)
                text.EndEdit();
            text = null;
            updateCurrentText();

            this.pageInfo = pageInfo;

            listBoxTextAreas.Items.Clear();
            for (int i = 0; i < pageInfo.Texts.Count; i++)
                listBoxTextAreas.Items.Add((i + 1).ToString());
            pageInfo.TextCreate = OnTextCreate;
            pageInfo.TextSelect = OnTextSelect;
            UpdateNames();
        }

        public void OnTextCreate(Text text)
        {
            if (this.text != null)
                this.text.EndEdit();
            this.text = text;
            checkBoxFill_CheckedChanged(null, null);
            checkBoxStroke_CheckedChanged(null, null);
            comboFontName_SelectedIndexChanged(null, null);
            numericFontSize_ValueChanged(null, null);
            checkBoxBold_CheckedChanged(null, null);
            checkBoxItalic_CheckedChanged(null, null);
            comboMode_SelectedIndexChanged(null, null);
            comboAlignment_SelectedIndexChanged(null, null);
            comboBaseline_SelectedIndexChanged(null, null);
            numericLineSpacing_ValueChanged(null, null);
            numericRotationDegrees_ValueChanged(null, null);
            comboType_SelectedIndexChanged(null, null);

            listBoxTextAreas.Items.Add(pageInfo.Texts.Count.ToString());
            listBoxTextAreas.SelectedIndex = pageInfo.Texts.Count - 1;
            UpdateNames();

            toolStripButtonTextSelect.Checked = true;
        }

        public void OnTextSelect(Text text)
        {
            listBoxTextAreas.SelectedIndex = pageInfo.Texts.IndexOf(text);
        }

        private void updateCurrentText()
        {
            if (pageEditor == null)
                return;
            if (text != null)
            {
                text.BeginEdit();
                pageEditor.UpdatePage();
            }
            textBox.Enabled = text != null;
        }

        private void resetToolStripText(ToolStripButton sender)
        {
            if (sender != toolStripButtonTextSelect)
                toolStripButtonTextSelect.Checked = false;
            if (sender != toolStripButtonTextWrite)
                toolStripButtonTextWrite.Checked = false;
        }

        private void toolStripButtonTextSelect_CheckedChanged(object sender, EventArgs e)
        {
            if (toolStripButtonTextSelect.Checked)
            {
                resetToolStripText(toolStripButtonTextSelect);
                pageEditor.TextSelect.Enable();
            }
            else
                pageEditor.TextSelect.Disable();
        }

        private void toolStripButtonTextWrite_CheckedChanged(object sender, EventArgs e)
        {
            if (toolStripButtonTextWrite.Checked)
            {
                resetToolStripText(toolStripButtonTextWrite);
                pageEditor.TextWrite.Enable();
            }
            else
                pageEditor.TextWrite.Disable();
        }

        private void buttonDelete_Click(object sender, EventArgs e)
        {
            if (listBoxTextAreas.SelectedIndex >= 0)
            {
                int i = listBoxTextAreas.SelectedIndex;
                pageInfo.Texts[i].Dispose();
                pageInfo.Texts.RemoveAt(i);
                listBoxTextAreas.Items.RemoveAt(i);
                if (i == listBoxTextAreas.Items.Count)
                    i--;
                if (i >= 0)
                    listBoxTextAreas.SelectedIndex = i;
                else
                {
                    text = null;
                    updateCurrentText();
                }
                pageEditor.UpdatePage();
                UpdateNames();
            }
        }

        private void listBoxTextAreas_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (text != null)
                text.EndEdit();
            text = null;
            textBox.Enabled = false;

            if (listBoxTextAreas.SelectedIndex >= 0)
            {
                Text newText = pageInfo.Texts[listBoxTextAreas.SelectedIndex];

                textBox.Text = newText.Formatted.Value;

                comboFontName.SelectedItem = newText.FontName;
                numericFontSize.Value = (decimal)newText.FontSize;
                checkBoxBold.Checked = newText.Bold;
                checkBoxItalic.Checked = newText.Italic;

                checkBoxFill.Checked = newText.Fill != null;
                if (checkBoxFill.Checked)
                {
                    labelFill.BackColor = Color.FromArgb(255, (newText.Fill as SolidBrush).Color);
                    numericFillOpacity.Value = (decimal)Math.Round((newText.Fill as SolidBrush).Color.A/2.55);
                }
                checkBoxStroke.Checked = newText.Stroke != null;
                if (checkBoxStroke.Checked)
                {
                    labelStroke.BackColor = Color.FromArgb(255, newText.Stroke.Color);
                    numericStrokeOpacity.Value = (decimal)Math.Round(newText.Stroke.Color.A/2.55);
                    numericStroke.Value = (decimal)newText.Stroke.Width;
                }

                if (newText.Vertical)
                    comboMode.SelectedIndex = 2;
                else if (newText.RightToLeft)
                    comboMode.SelectedIndex = 1;
                else
                    comboMode.SelectedIndex = 0;
                if (newText.Alignment == StringAlignment.Near)
                    comboAlignment.SelectedIndex = 0;
                if (newText.Alignment == StringAlignment.Center)
                    comboAlignment.SelectedIndex = 1;
                if (newText.Alignment == StringAlignment.Far)
                    comboAlignment.SelectedIndex = 2;
                comboBaseline.SelectedItem = newText.Baseline;

                if (numericLineSpacing.Minimum > (decimal)newText.LineSpacing)
                    numericLineSpacing.Minimum = (decimal)newText.LineSpacing;
                if (numericLineSpacing.Maximum < (decimal)newText.LineSpacing)
                    numericLineSpacing.Maximum = (decimal)newText.LineSpacing;
                numericLineSpacing.Value = (decimal)newText.LineSpacing;
                numericRotationDegrees.Value = (decimal)newText.RotateDegrees;

                comboType.Text = newText.Type;

                text = newText;
                updateCurrentText();
            }
        }

        private void checkBoxFill_CheckedChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                Brush fill = null;
                if (checkBoxFill.Checked)
                    fill = new SolidBrush(Color.FromArgb((int)Math.Round(2.55*(int)numericFillOpacity.Value), labelFill.BackColor));
                if (textBox.SelectionLength > 0)
                    text.Formatted.SetFill(textBox.SelectionStart, textBox.SelectionLength, fill);
                else
                    text.Fill = fill;
                pageEditor.UpdatePage();
            }
        }

        private void checkBoxStroke_CheckedChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                Pen stroke = null;
                if (checkBoxStroke.Checked)
                    stroke = new Pen(Color.FromArgb((int)Math.Round(2.55*(int)numericStrokeOpacity.Value), labelStroke.BackColor), (float)numericStroke.Value);
                if (textBox.SelectionLength > 0)
                    text.Formatted.SetStroke(textBox.SelectionStart, textBox.SelectionLength, stroke);
                else
                    text.Stroke = stroke;
                pageEditor.UpdatePage();
            }
        }

        private void numericStroke_ValueChanged(object sender, EventArgs e)
        {
            if (text != null && checkBoxStroke.Checked)
            {
                Pen stroke = new Pen(Color.FromArgb((int)Math.Round(2.55*(int)numericStrokeOpacity.Value), labelStroke.BackColor), (float)numericStroke.Value);
                if (textBox.SelectionLength > 0)
                    text.Formatted.SetStroke(textBox.SelectionStart, textBox.SelectionLength, stroke);
                else
                    text.Stroke = stroke;
                pageEditor.UpdatePage();
            }
        }

        private void labelFill_Click(object sender, EventArgs e)
        {
            colorDialog.Color = labelFill.BackColor;
            if (colorDialog.ShowDialog() == DialogResult.OK)
            {
                labelFill.BackColor = colorDialog.Color;
                if (text != null && checkBoxFill.Checked)
                {
                    Brush fill = new SolidBrush(Color.FromArgb((int)Math.Round(2.55*(int)numericFillOpacity.Value), labelFill.BackColor));
                    if (textBox.SelectionLength > 0)
                        text.Formatted.SetFill(textBox.SelectionStart, textBox.SelectionLength, fill);
                    else
                        text.Fill = fill;
                    pageEditor.UpdatePage();
                }
            }
        }

        private void labelStroke_Click(object sender, EventArgs e)
        {
            colorDialog.Color = labelStroke.BackColor;
            if (colorDialog.ShowDialog() == DialogResult.OK)
            {
                labelStroke.BackColor = colorDialog.Color;
                if (text != null && checkBoxStroke.Checked)
                {
                    Pen stroke = new Pen(Color.FromArgb((int)Math.Round(2.55*(int)numericStrokeOpacity.Value), labelStroke.BackColor), (float)numericStroke.Value);
                    if (textBox.SelectionLength > 0)
                        text.Formatted.SetStroke(textBox.SelectionStart, textBox.SelectionLength, stroke);
                    else
                        text.Stroke = stroke;
                    pageEditor.UpdatePage();
                }
            }
        }

        private void numericFillOpacity_ValueChanged(object sender, EventArgs e)
        {
            if (text != null && checkBoxFill.Checked)
            {
                Brush fill = new SolidBrush(Color.FromArgb((int)Math.Round(2.55*(int)numericFillOpacity.Value), labelFill.BackColor));
                if (textBox.SelectionLength > 0)
                    text.Formatted.SetFill(textBox.SelectionStart, textBox.SelectionLength, fill);
                else
                    text.Fill = fill;
                pageEditor.UpdatePage();
            }
        }

        private void numericStrokeOpacity_ValueChanged(object sender, EventArgs e)
        {
            if (text != null && checkBoxStroke.Checked)
            {
                Pen stroke = new Pen(Color.FromArgb((int)Math.Round(2.55*(int)numericStrokeOpacity.Value), labelStroke.BackColor), (float)numericStroke.Value);
                if (textBox.SelectionLength > 0)
                    text.Formatted.SetStroke(textBox.SelectionStart, textBox.SelectionLength, stroke);
                else
                    text.Stroke = stroke;
                pageEditor.UpdatePage();
            }
        }

        private void comboFontName_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                if (textBox.SelectionLength > 0)
                    text.Formatted.SetFontName(textBox.SelectionStart, textBox.SelectionLength, comboFontName.Text);
                else
                    text.FontName = comboFontName.Text;
                pageEditor.UpdatePage();
            }
        }

        private void numericFontSize_ValueChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                if (textBox.SelectionLength > 0)
                    text.Formatted.SetFontSize(textBox.SelectionStart, textBox.SelectionLength, (float)numericFontSize.Value);
                else
                    text.FontSize = (float)numericFontSize.Value;
                pageEditor.UpdatePage();
            }
        }

        private void checkBoxBold_CheckedChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                if (textBox.SelectionLength > 0)
                    text.Formatted.SetBold(textBox.SelectionStart, textBox.SelectionLength, checkBoxBold.Checked);
                else
                    text.Bold = checkBoxBold.Checked;
                pageEditor.UpdatePage();
            }
        }

        private void checkBoxItalic_CheckedChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                if (textBox.SelectionLength > 0)
                    text.Formatted.SetItalic(textBox.SelectionStart, textBox.SelectionLength, checkBoxItalic.Checked);
                else
                    text.Italic = checkBoxItalic.Checked;
                pageEditor.UpdatePage();
            }
        }

        private void comboMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboMode.SelectedIndex == 0)
            {
                comboAlignment.Items[0] = "left";
                comboAlignment.Items[1] = "center";
                comboAlignment.Items[2] = "right";
            }
            if (comboMode.SelectedIndex == 1)
            {
                comboAlignment.Items[0] = "right";
                comboAlignment.Items[1] = "center";
                comboAlignment.Items[2] = "left";
            }
            if (comboMode.SelectedIndex == 2)
            {
                comboAlignment.Items[0] = "top";
                comboAlignment.Items[1] = "middle";
                comboAlignment.Items[2] = "bottom";
            }
            if (text != null)
            {
                if (comboMode.SelectedIndex == 0)
                {
                    if (text.Vertical)
                        comboBaseline.SelectedIndex = 0;
                    text.Vertical = false;
                    text.RightToLeft = false;
                }
                if (comboMode.SelectedIndex == 1)
                {
                    if (text.Vertical)
                        comboBaseline.SelectedIndex = 0;
                    text.Vertical = false;
                    text.RightToLeft = true;
                }
                if (comboMode.SelectedIndex == 2)
                {
                    if (!text.Vertical)
                        comboBaseline.SelectedIndex = 1;
                    text.Vertical = true;
                    text.RightToLeft = true;
                }
                pageEditor.UpdatePage();
            }
        }

        private void comboAlignment_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                if (comboAlignment.SelectedIndex == 0)
                    text.Alignment = StringAlignment.Near;
                if (comboAlignment.SelectedIndex == 1)
                    text.Alignment = StringAlignment.Center;
                if (comboAlignment.SelectedIndex == 2)
                    text.Alignment = StringAlignment.Far;
                pageEditor.UpdatePage();
            }
        }

        private void comboBaseline_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                text.Baseline = (string)comboBaseline.SelectedItem;
                pageEditor.UpdatePage();
            }
        }

        private void numericLineSpacing_ValueChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                text.LineSpacing = (float)numericLineSpacing.Value;
                pageEditor.UpdatePage();
            }
        }

        private void numericRotationDegrees_ValueChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                text.RotateDegrees = (float)numericRotationDegrees.Value;
                pageEditor.UpdatePage();
            }
        }

        private void textBox_TextChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                int first, last;
                string oldText = text.Formatted.Value;
                string newText = textBox.Text;
                for (first = 0; first < oldText.Length && first < textBox.SelectionStart && oldText[first] == newText[first]; first++) ;
                for (last = 0; last < oldText.Length && last < newText.Length - textBox.SelectionStart && oldText[oldText.Length - last - 1] == newText[newText.Length - last - 1]; last++);
                if (first > oldText.Length - last)
                    first = oldText.Length - last;
                if (first > newText.Length - last)
                    first = newText.Length - last;
                text.Formatted.Replace(first, oldText.Length - first - last, textBox.Text.Substring(first, newText.Length - first - last));
                pageEditor.UpdatePage();
            }
        }

        private void toolStripButtonFonts_Click(object sender, EventArgs e)
        {
            FontDialog fontDialog = new FontDialog();
            fontDialog.ComicInfo = pageInfo.ComicInfo;
            fontDialog.ShowDialog();
            pageInfo.Page.Changed = true;
            pageEditor.UpdatePage();
        }

        private void comboType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (text != null)
            {
                text.Type = comboType.Text;
                UpdateNames();
            }
        }

        private void UpdateNames()
        {
            SortedList<string, int> types = new SortedList<string, int>();
            for (int i = 0; i < pageInfo.Texts.Count; i++)
            {
                string type = pageInfo.Texts[i].Type;
                if (type == "")
                    type = "Text";
                if (types.ContainsKey(type))
                    types[type]++;
                else
                    types.Add(type, 1);
                if (i < listBoxTextAreas.Items.Count)
                    listBoxTextAreas.Items[i] = type + " " + types[type];
            }
        }
    }
}
